package com.futvan.z.framework.util;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.futvan.z.framework.common.bean.Code;
import com.futvan.z.framework.common.bean.Result;
import com.futvan.z.framework.core.z;
public class FileUtil {
	/**
	 * 将图片流读出为图片
	 * 
	 * @param inputStream
	 * @param path
	 */
	private static void readBlob(InputStream inputStream, String path,String filename) {
		try {
			//判断目录是否存在，如果不存在自动创建
			mkdirs(path);
			FileOutputStream fileOutputStream = new FileOutputStream(path+filename);
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inputStream.read(buffer)) != -1) {
				fileOutputStream.write(buffer, 0, len);
			}
			inputStream.close();
			fileOutputStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 创建目录
	 * @param path
	 */
	public static String mkdirs(String path){
		File dir = new File(path);
		// 判断文件目录是否存在
		if (!dir.exists() && !dir.isDirectory()) {
			//自动创建多级目录
			dir.mkdirs();
		}
		return dir.getAbsolutePath();
	}
	
	/**
	 * 判读目标是否为空
	 * @param path
	 * @return
	 */
	public static boolean dirsIsNull(String path) {
		boolean result = false;
		if(z.isNotNull(path)) {
			File file = new File(path);
			//判读是否是目录
			if(file.isDirectory()){
				if(file.list().length<=0){
					result = true;
				}
			}
		}
		return result;
	}

	/**
	 * 创建文件(文本类)
	 * 
	 * @param FilePath
	 *            文件全路径
	 * @param TXTvalue
	 *            文本内容
	 * @throws Exception
	 */
	public static void createrTXT(String FilePath, String TXTvalue)throws Exception {
		if ("".equals(FilePath) || FilePath == null) {
			return;
		}
		File file = new File(FilePath);
		// 如果找到相同的文件，执行删除
		if (file.exists() && file.isFile()) {
			file.delete();
		}
		file.createNewFile();
		if (!"".equals(TXTvalue) && TXTvalue != null) {
			writeTXT(FilePath, TXTvalue, "");
		}
	}

	/**
	 * 打开文件
	 * 
	 * @param FilePath
	 *            文件路径
	 * @throws Exception
	 */
	public static void OpenFile(String FilePath) throws Exception {
		Runtime.getRuntime().exec(
				"cmd /c start \"\" \""
						+ FilePath.replaceAll("\\\\", "\\\\\\\\") + "\"");
	}

	/**
	 * 文本文件写入信息
	 * 
	 * @param FilePath
	 * @param value
	 * @throws Exception
	 */
	public static void writeTXT(String FilePath, String value, String encoding)
			throws Exception {
		File f = new File(FilePath);
		if (!f.exists()) {
			f.createNewFile();
		}
		if ("".equals(encoding) || encoding == null) {
			encoding = "UTF-8";
		}
		OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(
				f), encoding);
		BufferedWriter writer = new BufferedWriter(write);
		writer.write(value);
		writer.close();
	}

	/**
	 * 获取文件文本信息
	 * 
	 * @param filePath
	 *            路径
	 * @param encoding
	 *            编码格式 GBK UTF-8 GB2312
	 * @return StringBuffer
	 * @throws Exception
	 */
	public static String readFileTXT(String filePath, String encoding) throws Exception {
		StringBuffer returnvalue = new StringBuffer();
		if ("".equals(encoding) || encoding == null) {
			encoding = "UTF-8";
		}
		File file = new File(filePath);
		if (file.isFile() && file.exists()) { // 判断文件是否存在
			InputStreamReader read = new InputStreamReader(new FileInputStream(
					file), encoding);
			BufferedReader bufferedReader = new BufferedReader(read);
			String lineTxt = null;
			while ((lineTxt = bufferedReader.readLine()) != null) {
				returnvalue.append(lineTxt);
			}
			read.close();
		}
		return returnvalue.toString();
	}

	/**
	 * 数据压缩
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 * 
	 * 
	 *             实例： String inputStr =
	 *             "owolf@zlex.orgzlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org"
	 *             ;
	 * 
	 *             System.err.println("压缩前:\t" + inputStr); byte[] input =
	 *             inputStr.getBytes(); System.err.println("压缩前长度:\t" +
	 *             input.length);
	 * 
	 * 
	 *             System.err.println(); byte[] data = FileUtil.compress(input);
	 *             System.err.println("压缩后长度:\t" + data.length);
	 *             System.err.println();
	 * 
	 *             byte[] output = FileUtil.decompress(data); String outputStr =
	 *             new String(output); System.err.println("解压后:\t" + outputStr);
	 *             System.err.println("解压后长度:\t" + output.length);
	 * 
	 * 
	 * 
	 */
	public static byte[] compress(byte[] data) throws Exception {
		byte[] output = null;
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 压缩
		GZIPOutputStream gos = new GZIPOutputStream(baos);
		int count;
		byte dataByte[] = new byte[data.length];
		while ((count = bais.read(dataByte, 0, data.length)) != -1) {
			gos.write(dataByte, 0, count);
		}
		gos.finish();
		gos.flush();
		gos.close();

		output = baos.toByteArray();
		baos.flush();
		baos.close();
		bais.close();
		return output;
	}

	/**
	 * 数据解压缩
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] decompress(byte[] data) throws Exception {
		byte[] output = null;
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 解压缩
		GZIPInputStream gis = new GZIPInputStream(bais);
		int count;
		byte dataByte[] = new byte[data.length];
		while ((count = gis.read(dataByte, 0, data.length)) != -1) {
			baos.write(dataByte, 0, count);
		}
		gis.close();

		output = baos.toByteArray();

		baos.flush();
		baos.close();

		bais.close();
		return output;
	}

	/**
	 * 遍历文件夹
	 * @param path 目录
	 * @return List<String>
	 */
	public static List<File> getPathFiles(String path) {
		List<File> files = new ArrayList<File>();
		return getFiles(path,files,false,null);
	}
	/**
	 * 遍历文件夹
	 * @param path 目录
	 * @param extension 文件扩展名 
	 * @return List<String>
	 */
	public static List<File> getPathFiles(String path,String extension) {
		List<File> files = new ArrayList<File>();
		return getFiles(path,files,false,extension);
	}
	/**
	 * 遍历文件夹【查看下级文件夹】
	 * @param path 目录
	 * @return List<String>
	 */
	public static List<File> getPathAllFiles(String path) {
		List<File> files = new ArrayList<File>();
		return getFiles(path,files,true,null);
	}
	/**
	 * 遍历文件夹【查看下级文件夹】
	 * @param path 目录
	 * @param extension 文件扩展名 
	 * @return List<String>
	 */
	public static List<File> getPathAllFiles(String path,String extension) {
		List<File> files = new ArrayList<File>();
		return getFiles(path,files,true,extension);
	}
	private static List<File> getFiles(String path,List<File> files,boolean isLower,String extension){
		if(z.isNull(files)) {
			files = new ArrayList<File>();
		}
		//获取本级目录所有文件与文件夹对象
		File dir = new File(path);
		File[] filesArray = dir.listFiles();
		//如果本级目录没有文件与文件夹，直接返回
		if (filesArray == null)
			return files;
		for (int i = 0; i < filesArray.length; i++) {
			//判读是否查找下级目录
			if (filesArray[i].isDirectory() && isLower) {
				getFiles(filesArray[i].getAbsolutePath(),files,isLower,extension);
			} else {
				//判读是否是目录
				if (!filesArray[i].isDirectory()) {
					//当前文件名
					String nowFileName = filesArray[i].getAbsolutePath().toLowerCase();
					//查找指定扩展名文件
					if(z.isNotNull(extension)) {
						if(!".".equals(extension.substring(0, 1))) {
							extension = "."+extension;
						}
						String nowFileExtension = nowFileName.substring(nowFileName.length()-extension.length());
						//如果当前文件扩展名与查找目标扩展名相同，加入到返回结果
						if(nowFileExtension.equals(extension)) {
							files.add(filesArray[i]);
						}
					}else {
						files.add(filesArray[i]);
					}
				}
			}
		}
		return files;
	}
	
	public static void main(String[] args) {
	}


	/**
	 * 递归删除目录下的所有文件及子目录下所有文件
	 * 
	 * @param dir
	 *            将要删除的文件目录
	 * @return boolean Returns "true" if all deletions were successful. If a
	 *         deletion fails, the method stops attempting to delete and returns
	 *         "false".
	 */
	public static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			// 递归删除目录中的子目录下
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		}
		// 目录此时为空，可以删除
		return dir.delete();
	}
	
	/**
	 * 删除目录中指定文件
	 * @param extension 文件扩展名
	 * @return
	 */
	public static int removeDirFile(File dir,String extension) {
		int removeNum = 0;
		if (dir.isDirectory() && z.isNotNull(extension)) {
			String[] children = dir.list();
			// 递归删除目录中的子目录下
			for (int i = 0; i < children.length; i++) {
				if(!".".equals(extension.substring(0, 1))) {
					extension = "."+extension;
				}
				
				File f = new File(dir, children[i]);
				String nowFileName = f.getAbsolutePath().toLowerCase();
				String nowFileExtension = nowFileName.substring(nowFileName.length()-extension.length());
				//如果当前文件扩展名与查找目标扩展名相同，加入到返回结果
				if(nowFileExtension.equals(extension)) {
					//删除文件
					f.delete();
					removeNum = removeNum+1;
				}
				
			}
		}
		return removeNum;
	}
	
	/**
	 * 清空目录
	 * @param dir
	 * @return
	 */
	public static boolean clearDir(File dir) {
		boolean result = true;
		if (dir.isDirectory()) {
			String[] children = dir.list();
			// 递归删除目录中的子目录下
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					result = false;
				}
			}
		}else {
			result = false;
		}
		return result;
	}
	

	/**
	 * 移动文件
	 * 
	 * @param Path
	 *            文件
	 */
	public static void moveFile(String Path, String toPath) {
		// File (or directory) to be moved 
		File file = new File(Path); 

		// Destination directory 
		File dir = new File(toPath); 

		// Move file to new directory 
		file.renameTo(new File(dir, file.getName())); 
	}

	/**
	 * 复制单个文件
	 * @param oldPath String 原文件路径如：c:/fqf.txt
	 * @param newPath String 复制后路径如：f:/fqf.txt
	 */
	public static void copyFile(String oldPath, String newPath)
	{
		try
		{
			int bytesum = 0;
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists())
			{
				//文件存在时
				InputStream inStream = new FileInputStream(oldPath); //读入原文件
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1444];
				while ( (byteread = inStream.read(buffer)) != -1)
				{
					bytesum += byteread; //字节数文件大小
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 获得指定文件的byte数组
	 */
	public static byte[] getBytes(String filePath) {
		byte[] buffer = null;
		try {
			File file = new File(filePath);
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buffer;
	}

	/**
	 * 根据byte数组，生成文件
	 */
	public static void getFile(byte[] bfile, String filePath, String fileName) {
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		File file = null;
		try {
			File dir = new File(filePath);
			if (!dir.exists() && dir.isDirectory()) {// 判断文件目录是否存在
				dir.mkdirs();
			}
			file = new File(filePath + "\\" + fileName);
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			bos.write(bfile);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
	}

	/**
	 * 删除文件
	 * @param url 文件URL路径
	 * @return 返回删除状态
	 */
	public static Result DeleteFile(String url) {
		Result result = new Result();
		if(z.isNotNull(url)) {
			String path = url.replace(z.sp.get("fileserverurl"), "");
			//获取目标和文件信息  结果：  XXXXXXXXXXXXXXXXXXXX/XXX.jpg
			String[] pathArray = url.replace(z.sp.get("fileserverurl")+"/files/", "").split("/");
			String project_path = System.getProperty("web.root");
			File f = new File(project_path+path);
			if (f.exists()) {
				boolean b = f.delete();
				if(b) {
					//同时删除 z5 z1压缩版
					String fileName_z1 = pathArray[1].substring(0, pathArray[1].lastIndexOf(".")) +"_z1." + pathArray[1].substring(pathArray[1].lastIndexOf(".")+1);
					File f_z1 = new File(project_path+"/files/"+pathArray[0]+"/"+fileName_z1);
					f_z1.delete();
					String fileName_z5 = pathArray[1].substring(0, pathArray[1].lastIndexOf(".")) +"_z5." + pathArray[1].substring(pathArray[1].lastIndexOf(".")+1);
					File f_z5 = new File(project_path+"/files/"+pathArray[0]+"/"+fileName_z5);
					f_z5.delete();
					
					//删除成功后，判读文件夹是否为空，如果为空删文件夹
					String dirPath = project_path+"/files/"+pathArray[0];
					if(dirsIsNull(dirPath)) {
						File dir = new File(dirPath);
						dir.delete();
					}
					
					result.setCode(Code.SUCCESS);
					result.setMsg("删除文件成功");
				}else {
					result.setCode(Code.ERROR);
					result.setMsg("服务器中无法删除该文件");
				}
			}else {
				result.setCode(Code.SUCCESS);
				result.setMsg("服务器中未找到该文件");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("url is null");
		}
		return result;
	}

	/**
	 * 文件上传
	 * @param filename 文件名
	 * @param file  文件流
	 * @return
	 */
	public static String UploadFile(String filename, InputStream file) {
		String url = "";
		try {
			CloseableHttpClient httpclient = HttpClients.createDefault();
			HttpPost httppost = new HttpPost(z.sp.get("fileserverurl")+"/upload?filepath="+z.newNumber());
			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.addBinaryBody("cms_img", file, ContentType.create("multipart/form-data"), filename);
			HttpEntity httpEntity = builder.build();
			httppost.setEntity(httpEntity);

			//创建返回信息处理类
			ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
				public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
					String resultURL = "";
					//获取请求状态
					int status = response.getStatusLine().getStatusCode();
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						//如果返回信息不为空，直接输出。
						String Resultjson =  entity != null ? EntityUtils.toString(entity,"utf-8"):"";
						if(!"".equals(Resultjson) && Resultjson!=null) {
							Result result = JsonUtil.getObject(Resultjson, Result.class);
							if(result.code.equals(Code.SUCCESS)) {
								resultURL = String.valueOf(result.getData());
							}else {
								z.Error("HTTP ERROR : " + result.code+" | "+result.getMsg());
							}
						}
					} else {
						z.Error("HTTP ERROR : " + status);

					}
					return resultURL;
				}
			};
			url = httpclient.execute(httppost, responseHandler);
		} catch (Exception e) {
			z.Error("HTTP ERROR : " , e);
		}

		return url;
	}
	
	/**
	 * 创建文件存储目录
	 * @param filepath
	 * @return
	 * @throws Exception
	 */
	public static String CreateFileSavePath(String filepath) throws Exception{
		String fileSavePath = "";
		String project_path = System.getProperty("web.root");
		if(!"".equals(project_path) && project_path!=null) {
			fileSavePath = project_path;
			//判读路径是否为空
			if(!"".equals(filepath) && filepath!=null) {
				fileSavePath = fileSavePath+"/files/"+filepath;
			}

			// 判断文件目录是否存在如果不存在怎么创建
			File dir = new File(fileSavePath);
			if (!dir.exists() && !dir.isDirectory()) {
				//创建多级目录
				dir.mkdirs();
			}
		}else {
			throw new Exception("文件服务器系统错误:创建文件保存路径出错");
		}
		return fileSavePath;
	}
}
